package xyz.prob.kun.base.security.config;

import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.configuration.AuthenticationConfiguration;
import org.springframework.security.config.annotation.method.configuration.EnableMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import xyz.prob.kun.base.configData.IgnoreUrlsConfig;
import xyz.prob.kun.base.security.filter.JwtAuthenticationTokenFilter;
import xyz.prob.kun.base.security.handler.AuthenticationEntryPointImpl;

import java.util.List;

@Configuration
@EnableWebSecurity
@EnableMethodSecurity(securedEnabled = true)
public class KunSecurityConfig {

    @Resource
    private IgnoreUrlsConfig ignoreUrlsConfig;
    @Resource
    private AuthenticationEntryPointImpl authenticationEntryPoint;

    @Resource
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    @Resource(name = "userDetailServiceImpl")
    private UserDetailsService userDetailsService;

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity) throws Exception {
        List<String> urls = ignoreUrlsConfig.getUrls();
        String[] urlsArr = new String[urls.size()];
        urls.toArray(urlsArr);
        httpSecurity
                .authorizeHttpRequests((authorizeHttpRequests) ->
                        authorizeHttpRequests
                                // 遍历白名单，将白名单中的 URL 配置为完全公开，不需要任何权限
                                .requestMatchers(urlsArr).permitAll()
                                // 允许所有 OPTIONS 请求（通常用于 CORS 预检请求）
                                .requestMatchers(HttpMethod.OPTIONS).permitAll()
                                // 配置其他所有请求都需要认证
                                .anyRequest().authenticated())
                // 禁用 CSRF 保护（在使用 token 时通常不需要）
                .csrf(AbstractHttpConfigurer::disable)
                // 配置 session 策略为无状态，即不创建 session
                .sessionManagement(AbstractHttpConfigurer::disable)
                // 配置异常处理器
                .exceptionHandling(exceptionConfigurer->
                        // 当访问被拒绝时使用自定义的处理器返回响应
                        //.accessDeniedHandler()
                        // 当未认证或 token 过期时使用自定义的处理器返回响应
                        //.authenticationEntryPoint()
                    exceptionConfigurer.authenticationEntryPoint(authenticationEntryPoint)
                )
                .userDetailsService(userDetailsService)
                // 在 UsernamePasswordAuthenticationFilter 之前添加 JWT 拦截器
                .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);


        return httpSecurity.build();
    }


    /**
     * 身份认证管理器，调用authenticate()方法完成认证
     */
    @Bean
    public AuthenticationManager authenticationManager(AuthenticationConfiguration authenticationConfiguration) throws Exception {
        return authenticationConfiguration.getAuthenticationManager();
    }


    /**
     * 密码加密器
     */
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }



}
